import { MutableRefObject, useEffect } from 'react';

// 缓存对象与监听器函数
let listenerCallbacks = new WeakMap();
// 监听器
let observer: IntersectionObserver | undefined;

// 监听器处理函数
function handleIntersections(entries: IntersectionObserverEntry[]) {
  // 所有观测目标对象 entries
  entries.forEach((entry: IntersectionObserverEntry) => {
    // weakMap中是否缓存了DOM对象
    if (listenerCallbacks.has(entry.target)) {
      // 从缓存Map方法中取出响应的方法
      let cb = listenerCallbacks.get(entry.target);

      // entry.intersectionRatio  元素的能见率 entry.isIntersecting是否处于橡胶的状态
      if (entry.isIntersecting || entry.intersectionRatio > 0) {
        // 删除监听者
        observer!.unobserve(entry.target);
        // 删除weakMap缓存函数
        listenerCallbacks.delete(entry.target);
        cb();
      }
    }
  });
}

// 获取监听器
function getIntersectionObserver() {
  if (observer === undefined) {
    observer = new IntersectionObserver(handleIntersections, {
      rootMargin: '100px',
      threshold: 0.15
    });
  }
  return observer; //创建观察者对象
}

export function useObserve(elem: MutableRefObject<HTMLDivElement>, callback: () => void) {
  useEffect(() => {
    // 获取dom引用
    let target = elem.current;
    // 获取观察者
    let observer = getIntersectionObserver();
    // 将dom 与 回调函数相互对应
    listenerCallbacks.set(target, callback);
    // 观查者观测目标dom是否进入视图
    observer.observe(target);

    return () => {
      // 当dom销毁时删除目标DOM
      listenerCallbacks.delete(target);
      // 观察者停止对目标进行观察
      observer.unobserve(target);
    };
  }, [elem, callback]);
}

